package com.quiz.bis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quiz.bis.domain.bo.AppealHandleBo;
import com.quiz.bis.domain.bo.ManualCorrectBo;
import com.quiz.bis.domain.bo.ScoreQueryBo;
import com.quiz.bis.domain.model.*;
import com.quiz.bis.domain.vo.*;
import com.quiz.bis.mapper.*;
import com.quiz.bis.service.IScoreService;
import com.quiz.common.core.domain.R;
import com.quiz.common.core.domain.entity.SysUser;
import com.quiz.common.exception.ServiceException;
import com.quiz.common.mybatis.core.page.PageQuery;
import com.quiz.common.mybatis.core.page.TableDataInfo;
import com.quiz.common.mybatis.core.query.MPJLambdaWrapperPlus;
import com.quiz.common.mybatis.core.query.PlusWrappers;
import com.quiz.common.utils.SecurityUtils;
import com.quiz.common.utils.StringUtils;
import com.quiz.common.utils.bean.BeanUtils;
import com.quiz.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 分数管理服务实现
 *
 * @author ahuan
 */
@Service
@RequiredArgsConstructor
public class ScoreServiceImpl implements IScoreService {
    private final ExamMapper examMapper;
    private final ExamStudentRecordMapper recordMapper;
    private final ExamQuestionAnswersMapper questionAnswersMapper;
    private final PaperMapper paperMapper;
    private final PaperQuestionMapper paperQuestionMapper;
    private final QuestionMapper questionMapper;
    private final QuestionTypeMapper questionTypeMapper;
    private final SysUserMapper userMapper;
    private final ExamScoreAppealsMapper appealsMapper;
    private final QuestionOptionMapper questionOptionMapper;
    private final QuestionAnswerMapper questionAnswerMapper;
    private final QuestionCategoryRelationMapper questionCategoryRelationMapper;
    private final QuestionCategoryMapper questionCategoryMapper;

    @Override
    public TableDataInfo<ExamScoreSummaryVo> pageExamScoreList(ScoreQueryBo query, PageQuery pageQuery) {
        // 查询已结束的考试
        Page<Exam> page = examMapper.selectPage(pageQuery.build(),
                PlusWrappers.lambdaQuery(Exam.class)
                        .eq(Exam::getExamGroupId, query.getGroupId())
                        .eqIfPresent(Exam::getType, query.getType())
                        .eq(Exam::getStatus, 1) // 已发布
                        .lt(Exam::getEndTime, new Date()) // 已结束
                        .orderByDesc(Exam::getEndTime)
        );

        // 转换为VO
        List<ExamScoreSummaryVo> vos = page.getRecords().stream().map(exam -> {
            ExamScoreSummaryVo vo = new ExamScoreSummaryVo();
            vo.setId(exam.getId().toString());
            vo.setTitle(exam.getTitle());
            vo.setType(exam.getType());
            vo.setEndTime(exam.getEndTime());
            vo.setScorePubedStatus(exam.getScorePubedStatus());

            // 获取统计信息
            List<ExamStudentRecord> records = recordMapper.selectList(
                    Wrappers.lambdaQuery(ExamStudentRecord.class)
                            .eq(ExamStudentRecord::getExamId, exam.getId())
                            .eq(ExamStudentRecord::getStatus, 2) // 已提交
            );

            if (!records.isEmpty()) {
                // 参与人数
                vo.setParticipantCount(records.size());

                // 平均分
                BigDecimal avgScore = records.stream()
                        .map(ExamStudentRecord::getScore)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(BigDecimal.valueOf(records.size()), 2, RoundingMode.HALF_UP);
                vo.setAvgScore(avgScore);

                // 最高分
                BigDecimal maxScore = records.stream()
                        .map(ExamStudentRecord::getScore)
                        .filter(Objects::nonNull)
                        .max(Comparator.naturalOrder())
                        .orElse(BigDecimal.ZERO);
                vo.setHighestScore(maxScore);

                // 最低分
                BigDecimal minScore = records.stream()
                        .map(ExamStudentRecord::getScore)
                        .filter(Objects::nonNull)
                        .min(Comparator.naturalOrder())
                        .orElse(BigDecimal.ZERO);
                vo.setLowestScore(minScore);

                // 通过率
                Paper paper = paperMapper.selectById(exam.getPaperId());
                if (paper != null && paper.getPassScore() != null) {
                    long passCount = records.stream()
                            .filter(r -> r.getScore() != null && r.getScore().compareTo(paper.getPassScore()) >= 0)
                            .count();
                    vo.setPassRate(new BigDecimal(passCount * 100).divide(
                            new BigDecimal(records.size()), 2, RoundingMode.HALF_UP));
                }
            }

            return vo;
        }).collect(Collectors.toList());

        return TableDataInfo.build(vos, page.getTotal());
    }

    @Override
    public ExamScoreSummaryVo getExamSummary(Long examId) {
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            throw new ServiceException("考试不存在");
        }

        ExamScoreSummaryVo vo = new ExamScoreSummaryVo();
        vo.setId(exam.getId().toString());
        vo.setTitle(exam.getTitle());
        vo.setType(exam.getType());
        vo.setEndTime(exam.getEndTime());

        // 获取试卷信息
        Paper paper = paperMapper.selectById(exam.getPaperId());
        if (paper != null) {
            vo.setPaperTitle(paper.getTitle());
            vo.setTotalScore(paper.getTotalScore());
            vo.setPassScore(paper.getPassScore());
        }

        // 获取考生记录
        List<ExamStudentRecord> records = recordMapper.selectList(
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getStatus, 2) // 已提交
        );

        if (!records.isEmpty()) {
            // 基本统计
            vo.setParticipantCount(records.size());

            // 分数统计
            BigDecimal sumScore = records.stream()
                    .map(ExamStudentRecord::getScore)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setAvgScore(sumScore.divide(BigDecimal.valueOf(records.size()), 2, RoundingMode.HALF_UP));

            vo.setHighestScore(records.stream()
                    .map(ExamStudentRecord::getScore)
                    .filter(Objects::nonNull)
                    .max(Comparator.naturalOrder())
                    .orElse(BigDecimal.ZERO));

            vo.setLowestScore(records.stream()
                    .map(ExamStudentRecord::getScore)
                    .filter(Objects::nonNull)
                    .min(Comparator.naturalOrder())
                    .orElse(BigDecimal.ZERO));

            // 通过率
            if (paper != null && paper.getPassScore() != null) {
                long passCount = records.stream()
                        .filter(r -> r.getScore() != null && r.getScore().compareTo(paper.getPassScore()) >= 0)
                        .count();
                vo.setPassRate(new BigDecimal(passCount * 100).divide(
                        new BigDecimal(records.size()), 2, RoundingMode.HALF_UP));
            }

            // 分数段分布
            if (paper != null && paper.getTotalScore() != null) {
                Map<String, Long> scoreDistribution = calculateScoreDistribution(
                        records, paper.getTotalScore());
                vo.setScoreDistribution(scoreDistribution);
            }
        }

        return vo;
    }

    @Override
    public List<QuestionStatVo> getQuestionStats(Long examId) {
        // 获取试卷题目
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            throw new ServiceException("考试不存在");
        }

        List<PaperQuestion> paperQuestions = paperQuestionMapper.selectList(
                Wrappers.lambdaQuery(PaperQuestion.class)
                        .eq(PaperQuestion::getPaperId, exam.getPaperId())
                        .orderByAsc(PaperQuestion::getSort)
        );

        // 获取题目作答情况
        List<ExamQuestionAnswers> answers = questionAnswersMapper.selectList(
                Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                        .eq(ExamQuestionAnswers::getExamId, examId)
        );

        // 按题目分组
        Map<Long, List<ExamQuestionAnswers>> answersByQuestion = answers.stream()
                .collect(Collectors.groupingBy(ExamQuestionAnswers::getQuestionId));

        // 获取题目详情
        List<Long> questionIds = paperQuestions.stream()
                .map(PaperQuestion::getQuestionId)
                .collect(Collectors.toList());
        Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                .collect(Collectors.toMap(Question::getId, q -> q));

        // 构建题目统计VO
        return paperQuestions.stream().map(pq -> {
            QuestionStatVo vo = new QuestionStatVo();
            vo.setQuestionId(pq.getQuestionId());
            vo.setSort(pq.getSort());
            vo.setScore(pq.getScore());

            Question question = questionMap.get(pq.getQuestionId());
            if (question != null) {
                vo.setTitle(question.getTitle());
                vo.setTypeId(question.getTypeId().toString());
                vo.setDifficult(question.getDifficult());
            }

            // 题目作答统计
            List<ExamQuestionAnswers> questionAnswers = answersByQuestion.get(pq.getQuestionId());
            if (questionAnswers != null && !questionAnswers.isEmpty()) {
                // 平均得分
                BigDecimal avgScore = questionAnswers.stream()
                        .map(ExamQuestionAnswers::getScore)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(BigDecimal.valueOf(questionAnswers.size()), 2, RoundingMode.HALF_UP);
                vo.setAvgScore(avgScore);

                // 正确率
                long correctCount = questionAnswers.stream()
                        .filter(a -> a.getIsCorrect() != null && a.getIsCorrect() == 1)
                        .count();
                vo.setCorrectRate(new BigDecimal(correctCount * 100).divide(
                        new BigDecimal(questionAnswers.size()), 2, RoundingMode.HALF_UP));

                // 得分分布
                Map<String, Long> scoreDistribution = calculateQuestionScoreDistribution(
                        questionAnswers, pq.getScore());
                vo.setScoreDistribution(scoreDistribution);
            }

            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public TableDataInfo<StudentScoreVo> pageStudentScores(Long examId, PageQuery pageQuery, String searchKey) {
        // 查询考生记录
        Page<ExamStudentRecord> page = recordMapper.selectPage(pageQuery.build(),
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getStatus, 2) // 已提交
                        .like(StringUtils.isNotBlank(searchKey), ExamStudentRecord::getUserId, searchKey)
                        .orderByDesc(ExamStudentRecord::getScore)
        );

        // 获取用户信息
        List<Long> userIds = page.getRecords().stream()
                .map(ExamStudentRecord::getUserId)
                .collect(Collectors.toList());
        Map<Long, SysUser> userMap = userMapper.selectUserByIds(userIds).stream()
                .collect(Collectors.toMap(SysUser::getUserId, u -> u));

        // 转换为VO
        List<StudentScoreVo> vos = page.getRecords().stream().map(record -> {
            StudentScoreVo vo = new StudentScoreVo();
            vo.setRecordId(record.getId().toString());
            vo.setExamId(record.getExamId());
            vo.setUserId(record.getUserId());
            vo.setScore(record.getScore());
            vo.setSubmitTime(record.getSubmitTime());

            SysUser user = userMap.get(record.getUserId());
            if (user != null) {
                vo.setUserName(user.getUserName());
                vo.setNickName(user.getNickName());
            }

            return vo;
        }).collect(Collectors.toList());

        return TableDataInfo.build(vos, page.getTotal());
    }

    @Override
    public StudentExamScoreDetailVo getStudentExamDetail(Long recordId) {
        ExamStudentRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            throw new ServiceException("考试记录不存在");
        }

        StudentExamScoreDetailVo vo = new StudentExamScoreDetailVo();
        vo.setRecordId(record.getId().toString());
        vo.setUserId(record.getUserId());
        vo.setScore(record.getScore());
        vo.setSubmitTime(record.getSubmitTime());

        // 获取考试信息
        Exam exam = examMapper.selectById(record.getExamId());
        if (exam != null) {
            vo.setExamTitle(exam.getTitle());
            vo.setExamType(exam.getType());

            // 获取试卷信息
            Paper paper = paperMapper.selectById(exam.getPaperId());
            if (paper != null) {
                vo.setPaperTitle(paper.getTitle());
                vo.setTotalScore(paper.getTotalScore());
                vo.setPassScore(paper.getPassScore());
            }
        }

        // 获取用户信息
        SysUser user = userMapper.selectUserById(record.getUserId());
        if (user != null) {
            vo.setUserName(user.getUserName());
            vo.setNickName(user.getNickName());
        }

        // 获取题目作答详情
        List<ExamQuestionAnswers> answers = questionAnswersMapper.selectList(
                Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                        .eq(ExamQuestionAnswers::getStudentRecordId, recordId)
        );

        // 获取题目信息
        List<Long> questionIds = answers.stream()
                .map(ExamQuestionAnswers::getQuestionId)
                .collect(Collectors.toList());
        Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                .collect(Collectors.toMap(Question::getId, q -> q));

        // 获取题型信息
        List<Long> typeIds = questionMap.values().stream()
                .map(Question::getTypeId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, QuestionType> typeMap = questionTypeMapper.selectBatchIds(typeIds).stream()
                .collect(Collectors.toMap(QuestionType::getId, t -> t));

        // 构建题目详情VO
        List<StudentQuestionDetailVo> questionDetails = answers.stream().map(answer -> {
            StudentQuestionDetailVo detail = new StudentQuestionDetailVo();
            detail.setQuestionId(answer.getQuestionId());
            detail.setScore(answer.getScore());
            detail.setMaxScore(answer.getMaxScore());
            detail.setIsCorrect(answer.getIsCorrect());
            detail.setScoreStatus(answer.getScoreStatus());
            detail.setAnswerContent(answer.getAnswerContent());
            detail.setSelectedOptionCodes(answer.getSelectedOptionCodes());
            detail.setComment(answer.getCorrectComment());

            Question question = questionMap.get(answer.getQuestionId());
            if (question != null) {
                detail.setTitle(question.getTitle());
                detail.setContent(question.getContent());
                detail.setTypeId(question.getTypeId().toString());

                QuestionType type = typeMap.get(question.getTypeId());
                if (type != null) {
                    detail.setTypeName(type.getName());
                }
            }

            return detail;
        }).collect(Collectors.toList());

        vo.setQuestionDetails(questionDetails);
        return vo;
    }

    @Override
    @Transactional
    public R<Void> manualCorrect(ManualCorrectBo correctBo) {
        // 验证批改权限
        Exam exam = examMapper.selectById(correctBo.getExamId());
        if (exam == null) {
            return R.fail("考试不存在");
        }

        // 更新题目作答记录
        ExamQuestionAnswers answer = new ExamQuestionAnswers();
        answer.setId(correctBo.getAnswerId());
        answer.setManualScore(correctBo.getScore());
        answer.setScore(correctBo.getScore()); // 更新总分
        answer.setScoreStatus(2); // 人工评分完成
        answer.setCorrectComment(correctBo.getComment());
        answer.setCorrectBy(SecurityUtils.getUserId());
        answer.setCorrectTime(new Date());
        questionAnswersMapper.updateById(answer);

        // 更新学生考试记录总分
        updateStudentTotalScore(correctBo.getRecordId());

        return R.ok();
    }

    @Override
    public List<ManualCorrectQuestionVo> getManualCorrectQuestions(Long examId) {
        // 获取需要人工批改的题目列表
        List<ExamQuestionAnswers> answers = questionAnswersMapper.selectList(
                Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                        .eq(ExamQuestionAnswers::getExamId, examId)
                        .eq(ExamQuestionAnswers::getScoreStatus, 0) // 未评分
                        .or()
                        .eq(ExamQuestionAnswers::getExamId, examId)
                        .eq(ExamQuestionAnswers::getScoreStatus, 1) // 仅自动评分
        );

        // 按题目分组
        Map<Long, List<ExamQuestionAnswers>> answersByQuestion = answers.stream()
                .collect(Collectors.groupingBy(ExamQuestionAnswers::getQuestionId));

        // 获取题目信息
        List<Long> questionIds = new ArrayList<>(answersByQuestion.keySet());
        Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                .collect(Collectors.toMap(Question::getId, q -> q));

        // 构建VO
        return answersByQuestion.entrySet().stream().map(entry -> {
            ManualCorrectQuestionVo vo = new ManualCorrectQuestionVo();
            vo.setQuestionId(entry.getKey().toString());
            vo.setUncorrectedCount(entry.getValue().size());

            Question question = questionMap.get(entry.getKey());
            if (question != null) {
                vo.setTitle(question.getTitle());
                vo.setTypeId(question.getTypeId().toString());
            }

            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<ManualCorrectStudentVo> getManualCorrectStudents(Long examId) {
        // 获取需要人工批改的学生列表
        List<ExamStudentRecord> records = recordMapper.selectList(
                Wrappers.lambdaQuery(ExamStudentRecord.class)
                        .eq(ExamStudentRecord::getExamId, examId)
                        .eq(ExamStudentRecord::getStatus, 2) // 已提交
        );

        // 获取学生信息
        List<Long> userIds = records.stream()
                .map(ExamStudentRecord::getUserId)
                .collect(Collectors.toList());
        Map<Long, SysUser> userMap = userMapper.selectUserByIds(userIds).stream()
                .collect(Collectors.toMap(SysUser::getUserId, u -> u));

        // 构建VO
        return records.stream().map(record -> {
            ManualCorrectStudentVo vo = new ManualCorrectStudentVo();
            vo.setRecordId(record.getId().toString());
            vo.setUserId(record.getUserId());

            SysUser user = userMap.get(record.getUserId());
            if (user != null) {
                vo.setUserName(user.getUserName());
                vo.setNickName(user.getNickName());
            }

            // 获取未批改题目数量
            long uncorrectedCount = questionAnswersMapper.selectCount(
                    Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                            .eq(ExamQuestionAnswers::getStudentRecordId, record.getId())
                            .eq(ExamQuestionAnswers::getScoreStatus, 0) // 未评分
                            .or()
                            .eq(ExamQuestionAnswers::getStudentRecordId, record.getId())
                            .eq(ExamQuestionAnswers::getScoreStatus, 1) // 仅自动评分
            );
            vo.setUncorrectedCount((int) uncorrectedCount);

            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public R<Void> publishScore(Long examId) {
        Exam exam = new Exam();
        exam.setId(examId);
        exam.setScorePubedStatus(1); // 已发布成绩
        exam.setUpdateBy(SecurityUtils.getUserId().toString());
        exam.setUpdateTime(new Date());
        examMapper.updateById(exam);
        return R.ok();
    }

    @Override
    @Transactional
    public R<Void> handleAppeal(AppealHandleBo handleBo) {
        // 获取原来的申诉记录及改卷记录
        ExamScoreAppeals oldAppeal = appealsMapper.selectById(handleBo.getAppealId());
        if (oldAppeal == null) {
            return R.fail("申诉记录不存在");
        }
        ExamQuestionAnswers examQuestionAnswers = questionAnswersMapper.selectById(oldAppeal.getQuestionAnswerId());
        // 更新申诉记录
        ExamScoreAppeals appeal = new ExamScoreAppeals();
        appeal.setId(handleBo.getAppealId());
        appeal.setAppealStatus(2); // 已处理
        appeal.setHandlerId(SecurityUtils.getUserId());
        appeal.setHandleTime(new Date());
        appeal.setHandleResult(handleBo.getHandleResult());
        appeal.setOldScore(examQuestionAnswers.getScore());
        appealsMapper.updateById(appeal);

        // 如果需要调整分数
        if (handleBo.getAdjustScore() != null) {
            // 更新题目作答记录
            ExamQuestionAnswers answer = new ExamQuestionAnswers();
            answer.setId(handleBo.getAnswerId());
            answer.setScore(handleBo.getAdjustScore());
            answer.setCorrectComment(handleBo.getHandleResult());
            answer.setCorrectBy(SecurityUtils.getUserId());
            answer.setCorrectTime(new Date());
            questionAnswersMapper.updateById(answer);

            // 更新学生考试记录总分
            updateStudentTotalScore(handleBo.getRecordId());
        }

        return R.ok();
    }

    @Override
    public List<AppealVo> getAppealList(Long examId) {
        // 查询申诉记录
        List<ExamScoreAppeals> appeals = appealsMapper.selectList(
                Wrappers.lambdaQuery(ExamScoreAppeals.class)
                        .eq(ExamScoreAppeals::getExamId, examId)
                        .orderByDesc(ExamScoreAppeals::getAppealTime)
        );
        if (appeals.isEmpty()) {
            return Collections.emptyList();
        }

        // 获取学生信息
        List<Long> studentIds = appeals.stream()
                .map(ExamScoreAppeals::getStudentId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, SysUser> studentMap = userMapper.selectUserByIds(studentIds).stream()
                .collect(Collectors.toMap(SysUser::getUserId, u -> u));

        // 获取处理人信息
        List<Long> handlerIds = appeals.stream()
                .map(ExamScoreAppeals::getHandlerId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, SysUser> handlerMap = handlerIds.isEmpty() ?
                Collections.emptyMap() :
                userMapper.selectUserByIds(handlerIds).stream()
                        .collect(Collectors.toMap(SysUser::getUserId, u -> u));

        // 转换为VO
        return appeals.stream().map(appeal -> {
            AppealVo vo = new AppealVo();
            BeanUtils.copyProperties(appeal, vo);
            vo.setId(appeal.getId().toString());
            vo.setExamId(appeal.getExamId().toString());
            vo.setStudentId(appeal.getStudentId().toString());
            vo.setQuestionAnswerId(appeal.getQuestionAnswerId().toString());
            vo.setHandlerId(appeal.getHandlerId() == null ? null : appeal.getHandlerId().toString());
            vo.setQuestionId(appeal.getQuestionId().toString());

            // 设置学生信息
            SysUser student = studentMap.get(appeal.getStudentId());
            if (student != null) {
                vo.setStudentName(student.getNickName());
            }

            // 设置处理人信息
            if (appeal.getHandlerId() != null) {
                SysUser handler = handlerMap.get(appeal.getHandlerId());
                if (handler != null) {
                    vo.setHandlerName(handler.getNickName());
                }
            }

            return vo;
        }).collect(Collectors.toList());
    }

    // 辅助方法：更新学生考试记录总分
    private void updateStudentTotalScore(Long recordId) {
        ExamStudentRecord record = recordMapper.selectById(recordId);
        if (record != null) {
            // 重新计算总分
            BigDecimal totalScore = questionAnswersMapper.selectList(
                            Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                                    .eq(ExamQuestionAnswers::getStudentRecordId, recordId)
                    ).stream()
                    .map(ExamQuestionAnswers::getScore)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 更新记录
            ExamStudentRecord updateRecord = new ExamStudentRecord();
            updateRecord.setId(recordId);
            updateRecord.setScore(totalScore);
            updateRecord.setManualCorrected(1); // 已人工批改
            updateRecord.setManualCorrectBy(SecurityUtils.getUserId().toString());
            updateRecord.setManualCorrectTime(new Date());
            recordMapper.updateById(updateRecord);
        }
    }

    // 辅助方法：计算分数段分布
    private Map<String, Long> calculateScoreDistribution(List<ExamStudentRecord> records, BigDecimal totalScore) {
        Map<String, Long> distribution = new LinkedHashMap<>();
        distribution.put("90-100", 0L);
        distribution.put("80-89", 0L);
        distribution.put("70-79", 0L);
        distribution.put("60-69", 0L);
        distribution.put("0-59", 0L);

        for (ExamStudentRecord record : records) {
            if (record.getScore() == null) {
                continue;
            }

            double percentage = record.getScore().divide(totalScore, 4, RoundingMode.HALF_UP).doubleValue() * 100;

            if (percentage >= 90) {
                distribution.put("90-100", distribution.get("90-100") + 1);
            } else if (percentage >= 80) {
                distribution.put("80-89", distribution.get("80-89") + 1);
            } else if (percentage >= 70) {
                distribution.put("70-79", distribution.get("70-79") + 1);
            } else if (percentage >= 60) {
                distribution.put("60-69", distribution.get("60-69") + 1);
            } else {
                distribution.put("0-59", distribution.get("0-59") + 1);
            }
        }

        return distribution;
    }

    // 辅助方法：计算题目得分分布
    private Map<String, Long> calculateQuestionScoreDistribution(List<ExamQuestionAnswers> answers, BigDecimal maxScore) {
        Map<String, Long> distribution = new LinkedHashMap<>();
        distribution.put("满分", 0L);
        distribution.put("80%-99%", 0L);
        distribution.put("60%-79%", 0L);
        distribution.put("40%-59%", 0L);
        distribution.put("0%-39%", 0L);
        distribution.put("0分", 0L);

        for (ExamQuestionAnswers answer : answers) {
            if (answer.getScore() == null) {
                distribution.put("0分", distribution.get("0分") + 1);
                continue;
            }

            if (maxScore.compareTo(BigDecimal.ZERO) == 0) {
                continue;
            }

            double percentage = answer.getScore().divide(maxScore, 4, RoundingMode.HALF_UP).doubleValue() * 100;

            if (percentage >= 100) {
                distribution.put("满分", distribution.get("满分") + 1);
            } else if (percentage >= 80) {
                distribution.put("80%-99%", distribution.get("80%-99%") + 1);
            } else if (percentage >= 60) {
                distribution.put("60%-79%", distribution.get("60%-79%") + 1);
            } else if (percentage >= 40) {
                distribution.put("40%-59%", distribution.get("40%-59%") + 1);
            } else if (percentage > 0) {
                distribution.put("0%-39%", distribution.get("0%-39%") + 1);
            } else {
                distribution.put("0分", distribution.get("0分") + 1);
            }
        }

        return distribution;
    }


    @Override
    public QuestionDetailVo getQuestionDetail(Long questionId) {
        // 获取题目基本信息
        Question question = questionMapper.selectById(questionId);
        if (question == null) {
            throw new ServiceException("题目不存在");
        }

        QuestionDetailVo vo = new QuestionDetailVo();
        BeanUtils.copyProperties(question, vo);

        // 获取题目类型名称
        QuestionType questionType = questionTypeMapper.selectById(question.getTypeId());
        if (questionType != null) {
            vo.setTypeName(questionType.getName());
        }

        // 获取题目选项（如果是选择题）
        if (questionType != null && questionType.getHasOption() > 0) {
            List<QuestionOption> options = questionOptionMapper.selectList(
                    Wrappers.lambdaQuery(QuestionOption.class)
                            .eq(QuestionOption::getQuestionId, questionId)
                            .orderByAsc(QuestionOption::getSort)
            );
            vo.setOptions(options);
        }

        // 获取题目答案
        List<QuestionAnswer> answers = questionAnswerMapper.selectList(
                Wrappers.lambdaQuery(QuestionAnswer.class)
                        .eq(QuestionAnswer::getQuestionId, questionId)
                        .orderByAsc(QuestionAnswer::getSort)
        );
        vo.setAnswers(answers);

        return vo;
    }

    @Override
    public StudentAnswerVo getStudentAnswer(Long questionId, Long recordId, Long examId) {
        StudentAnswerVo vo = new StudentAnswerVo();

        if (questionId != null && examId != null) {
            // 模式1：按题目批改 - 获取该题目所有待批改的学生答案
            List<ExamQuestionAnswers> answers = questionAnswersMapper.selectList(
                    Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                            .eq(ExamQuestionAnswers::getQuestionId, questionId)
                            .eq(ExamQuestionAnswers::getExamId, examId)
                            .in(ExamQuestionAnswers::getScoreStatus, Arrays.asList(0, 1)) // 未批改或仅自动批改
                            .orderByAsc(ExamQuestionAnswers::getId)
            );

            if (!answers.isEmpty()) {
                // 获取学生信息
                List<Long> studentIds = answers.stream()
                        .map(ExamQuestionAnswers::getUserId)
                        .distinct()
                        .collect(Collectors.toList());
                Map<Long, SysUser> studentMap = userMapper.selectUserByIds(studentIds).stream()
                        .collect(Collectors.toMap(SysUser::getUserId, u -> u));

                // 构建VO
                vo.setAnswers(answers);

                List<SysUser> students = answers.stream()
                        .map(a -> studentMap.get(a.getUserId()))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                vo.setStudents(students);
            }
        } else if (recordId != null) {

            // 模式2：按学生批改 - 获取该学生所有待批改的题目
            ExamStudentRecord record = recordMapper.selectById(recordId);
            if (record == null) {
                throw new ServiceException("考试记录不存在");
            }

            // 获取学生信息
            SysUser student = userMapper.selectUserById(record.getUserId());
            vo.setStudent(student);

            // 获取待批改题目
            List<ExamQuestionAnswers> answers = questionAnswersMapper.selectList(
                    Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                            .eq(ExamQuestionAnswers::getStudentRecordId, recordId)
                            .in(ExamQuestionAnswers::getScoreStatus, Arrays.asList(0, 1)) // 未批改或仅自动批改
                            .orderByAsc(ExamQuestionAnswers::getId)
            );

            if (!answers.isEmpty()) {
                // 获取题目信息
                List<Long> questionIds = answers.stream()
                        .map(ExamQuestionAnswers::getQuestionId)
                        .collect(Collectors.toList());
                List<QuestionDetailVo> questions = questionMapper.selectQuestionDetailListByIds(questionIds);

                vo.setQuestions(questions);
                vo.setAnswers(answers);
            }
        } else {
            throw new ServiceException("参数错误：必须提供questionId+examId或recordId");
        }

        return vo;
    }

    @Override
    public ExamStatisticsPerStuVo getStudentExamStatistics(Long recordId) {
        ExamStatisticsPerStuVo vo = new ExamStatisticsPerStuVo();

        // 获取考试记录
        ExamStudentRecord record = recordMapper.selectById(recordId);
        if (record == null) {
            throw new ServiceException("考试记录不存在");
        }

        // 获取所有题目作答记录
        List<ExamQuestionAnswers> answers = questionAnswersMapper.selectList(
                Wrappers.lambdaQuery(ExamQuestionAnswers.class)
                        .eq(ExamQuestionAnswers::getStudentRecordId, recordId)
        );

        // 获取题目ID集合
        List<Long> questionIds = answers.stream()
                .map(ExamQuestionAnswers::getQuestionId)
                .collect(Collectors.toList());

        if (!questionIds.isEmpty()) {
            // 获取题目信息
            Map<Long, Question> questionMap = questionMapper.selectBatchIds(questionIds).stream()
                    .collect(Collectors.toMap(Question::getId, q -> q));

            // 获取题型信息
            List<Long> typeIds = questionMap.values().stream()
                    .map(Question::getTypeId)
                    .distinct()
                    .collect(Collectors.toList());
            Map<Long, QuestionType> typeMap = questionTypeMapper.selectBatchIds(typeIds).stream()
                    .collect(Collectors.toMap(QuestionType::getId, t -> t));

            // 获取知识点关联
            List<QuestionCategoryRelation> relations = questionCategoryRelationMapper.selectList(
                    Wrappers.lambdaQuery(QuestionCategoryRelation.class)
                            .in(QuestionCategoryRelation::getQuestionId, questionIds)
//                            .eq(QuestionCategoryRelation::getIsKnowledge, 1)
            );
            Map<Long, List<Long>> questionKnowledgeMap = relations.stream()
                    .collect(Collectors.groupingBy(
                            QuestionCategoryRelation::getQuestionId,
                            Collectors.mapping(QuestionCategoryRelation::getCategoryId, Collectors.toList())
                    ));

            // 获取知识点信息
            List<Long> knowledgeIds = relations.stream()
                    .map(QuestionCategoryRelation::getCategoryId)
                    .distinct()
                    .collect(Collectors.toList());
            Map<Long, QuestionCategory> knowledgeMap = knowledgeIds.isEmpty() ?
                    Collections.emptyMap() :
                    questionCategoryMapper.selectBatchIds(knowledgeIds).stream()
                            .collect(Collectors.toMap(QuestionCategory::getId, k -> k));

            // 1. 计算题型得分分布
            Map<Long, TypeScoreVo> typeScoreMap = new HashMap<>();
            answers.forEach(answer -> {
                Question question = questionMap.get(answer.getQuestionId());
                if (question != null) {
                    QuestionType type = typeMap.get(question.getTypeId());
                    if (type != null) {
                        TypeScoreVo typeScore = typeScoreMap.computeIfAbsent(type.getId(), k -> {
                            TypeScoreVo typeScoreVo = new TypeScoreVo();
                            typeScoreVo.setTypeId(type.getId());
                            typeScoreVo.setTypeName(type.getName());
                            typeScoreVo.setTotalScore(BigDecimal.ZERO);
                            typeScoreVo.setMaxScore(BigDecimal.ZERO);
                            return typeScoreVo;
                        });
                        typeScore.setTotalScore(typeScore.getTotalScore().add(answer.getScore()));
                        typeScore.setMaxScore(typeScore.getMaxScore().add(answer.getMaxScore()));
                    }
                }
            });

            // 计算百分比
            typeScoreMap.values().forEach(typeScoreVo -> {
                if (typeScoreVo.getMaxScore().compareTo(BigDecimal.ZERO) > 0) {
                    typeScoreVo.setPercentage(typeScoreVo.getTotalScore()
                            .divide(typeScoreVo.getMaxScore(), 4, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100")));
                } else {
                    typeScoreVo.setPercentage(BigDecimal.ZERO);
                }
            });

            vo.setTypeScores(new ArrayList<>(typeScoreMap.values()));

            // 2. 计算难度得分分布
            Map<Integer, DifficultyScoreVo> difficultyScoreMap = new HashMap<>();
            answers.forEach(answer -> {
                Question question = questionMap.get(answer.getQuestionId());
                if (question != null && question.getDifficult() != null) {
                    DifficultyScoreVo difficultyScore = difficultyScoreMap.computeIfAbsent(
                            question.getDifficult(), k -> {
                                DifficultyScoreVo difficultyScoreVo = new DifficultyScoreVo();
                                difficultyScoreVo.setDifficulty(k);
                                difficultyScoreVo.setDifficultyName(getDifficultyName(k));
                                difficultyScoreVo.setTotalScore(BigDecimal.ZERO);
                                difficultyScoreVo.setMaxScore(BigDecimal.ZERO);
                                return difficultyScoreVo;
                            });
                    difficultyScore.setTotalScore(difficultyScore.getTotalScore().add(answer.getScore()));
                    difficultyScore.setMaxScore(difficultyScore.getMaxScore().add(answer.getMaxScore()));
                }
            });

            // 计算百分比
            difficultyScoreMap.values().forEach(difficultyVo -> {
                if (difficultyVo.getMaxScore().compareTo(BigDecimal.ZERO) > 0) {
                    difficultyVo.setPercentage(difficultyVo.getTotalScore()
                            .divide(difficultyVo.getMaxScore(), 4, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100")));
                } else {
                    difficultyVo.setPercentage(BigDecimal.ZERO);
                }
            });

            vo.setDifficultyScores(new ArrayList<>(difficultyScoreMap.values()));

            // 3. 计算知识点掌握情况
            Map<Long, KnowledgeScoreVo> knowledgeScoreMap = new HashMap<>();
            answers.forEach(answer -> {
                Question question = questionMap.get(answer.getQuestionId());
                if (question != null) {
                    List<Long> knowledgeIdsForQuestion = questionKnowledgeMap.getOrDefault(
                            question.getId(), Collections.emptyList());
                    knowledgeIdsForQuestion.forEach(knowledgeId -> {
                        QuestionCategory knowledge = knowledgeMap.get(knowledgeId);
                        if (knowledge != null) {
                            KnowledgeScoreVo knowledgeScore = knowledgeScoreMap.computeIfAbsent(
                                    knowledgeId, k -> {
                                        KnowledgeScoreVo knowledgeScoreVo = new KnowledgeScoreVo();
                                        knowledgeScoreVo.setKnowledgeId(k);
                                        knowledgeScoreVo.setKnowledgeName(knowledge.getName());
                                        knowledgeScoreVo.setTotalScore(BigDecimal.ZERO);
                                        knowledgeScoreVo.setMaxScore(BigDecimal.ZERO);
                                        return knowledgeScoreVo;
                                    });
                            knowledgeScore.setTotalScore(knowledgeScore.getTotalScore().add(answer.getScore()));
                            knowledgeScore.setMaxScore(knowledgeScore.getMaxScore().add(answer.getMaxScore()));
                        }
                    });
                }
            });

            // 计算百分比
            knowledgeScoreMap.values().forEach(knowledgeVo -> {
                if (knowledgeVo.getMaxScore().compareTo(BigDecimal.ZERO) > 0) {
                    knowledgeVo.setPercentage(knowledgeVo.getTotalScore()
                            .divide(knowledgeVo.getMaxScore(), 4, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100")));
                } else {
                    knowledgeVo.setPercentage(BigDecimal.ZERO);
                }
            });

            vo.setKnowledgeScores(new ArrayList<>(knowledgeScoreMap.values()));
        }

        return vo;
    }

    @Override
    public ExamQuestionAnswers getStudentAnswerRecord(Long questionAnswerId) {
        return questionAnswersMapper.selectById(questionAnswerId);
    }

    private String getDifficultyName(Integer difficulty) {
        if (difficulty == null) {
            return "未知";
        }
        switch (difficulty) {
            case 1:
                return "容易";
            case 2:
                return "偏易";
            case 3:
                return "中等";
            case 4:
                return "偏难";
            case 5:
                return "困难";
            default:
                return "未知";
        }
    }


}